import * as crypto from 'crypto'
import { ObjectId, Binary } from 'mongodb'
import * as db from '../db'
import { stats } from '../stats'
import { IUser } from '../types'
import * as fs from 'fs'

export const tokens = new Map<string, ObjectId>()

// 注册
export async function register(record: IUser) {
  const user = await db.userCollection.findOne({
    username: record.username
  })
  if (user) return 'ERR_EXISTS'
  const hash = crypto.createHash('sha1')
  hash.update(record.password)
  record.password = hash.digest('hex')
  if (user === undefined) {
    const result = await db.userCollection.insertOne({
      username: record.username,
      password: record.password,
      name: '',
      sex: 1,
      isDisabled: 1,
      companyId: null,
      role: 2,
      companyShortName: '',
      positionName: ''
    })
    return 'ok'
  }
}

// 登录
export async function login(username: string, password: string) {
  const user = await db.userCollection.findOne({
    username: username
  })
  const hash = crypto.createHash('sha1')
  hash.update(password)
  password = hash.digest('hex')
  if (user === undefined) throw stats.ERR_USER_NOT_FOUND
  if (user.password !== password) {
    throw stats.ERR_LOGIN_FAILED
  }
  const token = crypto.randomBytes(12).toString('hex')
  tokens.set(token, user._id)
  return token
}

// 修改密码
export async function test(token: string, password: string) {
  const _id = tokens.get(token)
  const result = await db.userCollection.findOne({
    _id: new ObjectId(_id)
  })
  const hash = crypto.createHash('sha1')
  hash.update(password)
  password = hash.digest('hex')
  if (result.password !== password) {
    throw stats.ERR_LOGIN_FAILED
  }
}

// 获取用户信息
export async function userInfo(token: string) {
  const _id = tokens.get(token)
  const user = await db.userCollection.findOne(
    {
      _id: new ObjectId(_id)
    },
    {
      projection: {
        password: 0,
        isDisabled: 0
      }
    }
  )
  if (user === undefined) throw stats.ERR_NOT_LOGIN
  return user
}

// 根据id获取用户信息
export async function findUserInfo(_id: string) {
  const user = await db.userCollection.findOne({
    _id: new ObjectId(_id)
  })
  if (user === undefined) throw stats.ERR_NOT_LOGIN
  return user
}

// 添加/修改用户信息
export async function addInfo(token: string, record: IUser) {
  const _id = tokens.get(token)
  const result = await db.userCollection.findOne({
    _id: new ObjectId(_id)
  })
  if (result === null) {
    throw stats.ERR_EXISTS
  } else {
    if (record?.password) {
      const hash = crypto.createHash('sha1')
      hash.update(record.password)
      record.password = hash.digest('hex')
      const result = await db.userCollection.findOneAndUpdate(
        {
          _id: new ObjectId(_id)
        },
        {
          $set: record
        }
      )
      if (result === null) throw stats.ERR_NOT_FOUND
    } else {
      const result = await db.userCollection.findOneAndUpdate(
        {
          _id: new ObjectId(_id)
        },
        {
          $set: record
        }
      )
      if (result === null) throw stats.ERR_NOT_FOUND
    }
  }
}

// 退出登录
export async function logout(token: string) {
  tokens.delete(token)
}

// 获取用户列表
export async function userlist(id: string) {
  const user = await db.userCollection
    .find({
      companyId: new ObjectId(id)
    })
    .toArray()
  if (user === null) throw stats.ERR_NOT_FOUND
  return user
}

// 获取普通用户列表
export async function allUserlist(token: string) {
  const id = tokens.get(token)
  const use = await db.userCollection.findOne({
    _id: id
  })
  if (use.role !== 1) throw stats.ERR_NOT_FOUND
  const userList = await db.userCollection
    .find({
      role: { $nin: [1] }
    })
    .toArray()
  if (userList === null) throw stats.ERR_NOT_FOUND
  return userList
}

// 添加用户
export async function userAdd(username: string, id: string) {
  const user = await db.userCollection.findOne({
    username: username
  })
  if (user === undefined) throw stats.ERR_NOT_FOUND
  if (user.companyId !== null) throw stats.ERR_EXISTS
  await db.userCollection.findOneAndUpdate(
    {
      _id: user._id
    },
    {
      $set: {
        companyId: new ObjectId(id)
      }
    }
  )
}

// 删除用户
export async function removerUser(id: string) {
  const user = await db.companyCollection.findOneAndDelete({
    _id: new ObjectId(id)
  })
  if (user === null) throw stats.ERR_NOT_FOUND
  const result = await db.userCollection.findOneAndUpdate(
    {
      _id: user.value._id
    },
    {
      $set: {
        companyId: null
      }
    }
  )
  if (result === null) throw stats.ERR_NOT_FOUND
  return user.value
}
// 删除公司用户和删除用户、根据用户的权限来决定
export async function removerCompanyUser(id: string, token: string) {
  const superId = tokens.get(token)
  const superUser = await db.userCollection.findOne({
    _id: superId
  })
  if (superUser.role === 1) {
    await db.userCollection.findOneAndDelete({
      _id: new ObjectId(id)
    })
  } else {
    await db.userCollection.findOneAndUpdate(
      {
        _id: new ObjectId(id)
      },
      {
        $set: {
          companyId: null
        }
      }
    )
  }
}

// 修改用户
export async function edit(user: IUser, token: string) {
  const _id = tokens.get(token)
  if (user.password !== undefined) {
    const hash = crypto.createHash('sha1')
    hash.update(user.password)
    user.password = hash.digest('hex')
  }
  await db.userCollection.findOneAndUpdate(
    {
      _id: _id
    },
    {
      $set: user
    }
  )
}

// 系统管理员修改用户信息
export async function editPlus(user: IUser, token: string, id: string) {
  const _id = tokens.get(token)

  const res = await db.userCollection.findOne({
    _id: _id
  })
  if (res === undefined || res.role > 2) throw stats.ERR_FORBIDDEN
  if (user.companyId !== undefined) {
    user.companyId = new ObjectId(user.companyId)
  }
  await db.userCollection.findOneAndUpdate(
    {
      _id: new ObjectId(id)
    },
    {
      $set: user
    }
  )
}

// 查看是否收藏
export async function findFav(_id: ObjectId, id: string) {
  const result = await db.favCollection.findOne({
    id: _id,
    IRecruitId: new ObjectId(id)
  })
  return result
}

// 添加收藏
export async function addFav(token: string, IRecruitId: string) {
  const _id = tokens.get(token)
  const result = await db.userCollection.find({
    _id: new ObjectId(_id)
  })
  if (result !== undefined) {
    const item = await db.favCollection.insertOne({
      id: tokens.get(token),
      IRecruitId: new ObjectId(IRecruitId)
    })
    return item
  } else throw stats.ERR_USER_NOT_FOUND
}

// 我的收藏列表
export async function listFav(token: string) {
  const id = tokens.get(token)
  const data = await db.favCollection
    .aggregate([
      {
        $match: { id: id }
      },
      {
        $lookup: {
          from: 'recruit',
          localField: 'IRecruitId',
          foreignField: '_id',
          as: 'items'
        }
      }
    ])
    .toArray()
  if (data === undefined) throw stats.ERR_NOT_LOGIN
  return data
}

// 删除收藏
export async function removeFav(id: string) {
  const result = await db.favCollection.findOneAndDelete({
    IRecruitId: new ObjectId(id)
  })
  if (result === null) throw stats.ERR_NOT_FOUND
  return result
}

// 禁用恢复用户状态
export async function userStatus(id: string) {
  const user = await db.userCollection.findOne({
    _id: new ObjectId(id)
  })

  await db.userCollection.findOneAndUpdate(
    {
      _id: new ObjectId(id)
    },
    {
      $set: {
        isDisabled: user.isDisabled === 1 ? 2 : 1
      }
    }
  )
}

// 文件上传
export async function upload(
  token: string,
  path: string,
  size: number,
  name: string
) {
  console.log(path)
  console.log(name)
  const _id = tokens.get(token)
  const result = await db.userCollection.findOne({
    _id: new ObjectId(_id)
  })
  if (result === null) {
    throw stats.ERR_NOT_FOUND
  }
  const data = await fs.promises.readFile(path)
  await db.userCollection.findOneAndUpdate(
    {
      _id: new ObjectId(_id)
    },
    {
      $set: {
        avatar: { data: new Binary(data), name: name, size: size }
      }
    }
  )
  await fs.promises.unlink(path)
  return data
}

/**
 * 查找文件
 * @param id
 * @returns
 */
export async function download(id: string) {
  const result = await db.userCollection.findOne({
    _id: new ObjectId(id)
  })
  if (!result) throw stats.ERR_NOT_FOUND
  return result.avatar
}
